package com.lianxueda.drawing.controller;



import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.lianxueda.drawing.common.R;
import com.lianxueda.drawing.config.RandomUtil;
import com.lianxueda.drawing.config.TemplateMsgService;
import com.lianxueda.drawing.domain.dto.BindChildDTO;
import com.lianxueda.drawing.domain.dto.KaoQin;
import com.lianxueda.drawing.domain.pojo.Schedules;
import com.lianxueda.drawing.domain.pojo.Students;
import com.lianxueda.drawing.domain.pojo.WxUser;
import com.lianxueda.drawing.mapper.CoursesMapper;
import com.lianxueda.drawing.mapper.SchedulesMapper;
import com.lianxueda.drawing.mapper.StudentsMapper;
import com.lianxueda.drawing.mapper.WxUserMapper;
import com.lianxueda.drawing.service.MsmService;
import com.lianxueda.drawing.service.StudentsService;
import com.lianxueda.drawing.service.WxUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 29264
 */
@RestController
@RequestMapping("/api/mp")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "微信公众号模块")
public class WxMpController {

    private final WxMpService wxMpService;
    private final WxUserService wxUserService;
    private final StudentsService studentsService;
    @Resource
    private StudentsMapper studentsMapper;
    @Resource
    private SchedulesMapper schedulesMapper;
    @Resource
    private CoursesMapper coursesMapper;
    @Resource
    private WxUserMapper wxUserMapper;
    @Autowired
    private MsmService msmService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;    //注入redis

    @Resource
    private TemplateMsgService templateMsgService;

    private static final String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";


    @GetMapping("/getCode")
    @Operation(summary = "获取(更新)用户信息,")
    public void  authLogin(String code, HttpServletResponse response) {
        log.info("临时凭据：code = {}",code);
        try {
            WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
            String openId = wxOAuth2AccessToken.getOpenId();
            String accessToken = wxOAuth2AccessToken.getAccessToken();
            String getUserInfoURL = String.format(USER_INFO_URL, accessToken, openId);
            //获取用户信息
            String userInfoJson = HttpUtil.get(getUserInfoURL);
            WxUser wxUser = JSONUtil.toBean(userInfoJson,WxUser.class);
            log.info("用户信息：{}",wxUser.toString());
            // 首次授权登录，新增用户基本信息
            // 再次登录，更新用户信息（昵称、头像、更新时间等）操作
            // 处理用户信息
            if (wxUserService.userExists(openId)) {
                // 如果用户已存在，则更新用户信息
                wxUserService.updateUser(wxUser);
            } else {
                // 如果用户不存在，则新增用户
                wxUserService.addUser(wxUser);
            }
            response.sendRedirect("http://192.168.100.199:3000/index?openid=" + openId);
        } catch (WxErrorException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param echostr 随机字符串
     * @return
     */
    @GetMapping("/check")
    @Operation(summary = "验证签名")
    public String checkSignature(String signature,String timestamp,String nonce,String echostr){
        log.info("验签：signature = {},timestamp = {},nonce = {},echostr = {}",signature,timestamp,nonce,echostr);
        boolean valid = wxMpService.checkSignature(timestamp, nonce, signature);
        if(valid) {
            return echostr;
        }

        return "签名失败";
    }

    /**
     * 通知模板
     * @param openid
     * @return
     */

    @GetMapping("/sendMsg")
    @Operation(summary = "通知模板,暂时不用")
    public String notify(@RequestParam("openid") String openid){
        Map<String,String> contentMap = new LinkedHashMap<>();
        contentMap.put("parentName","张旭");
        contentMap.put("courseName","绘画初级班人物素描第一次课");
        contentMap.put("studentName","张小旭");
        contentMap.put("schoolTime","2024年08月30日 18:30至2024年08月30日 19:30");
        contentMap.put("classLocation","第102教室");
        String returnMsg =  templateMsgService.sendTemplateMsg(openid,contentMap);
        return returnMsg;
    }

    /**
     * 考勤通知模板
     */
    @PostMapping("/notify")
    @Operation(summary = "考勤通知模板")
    public R checkingIn(@RequestBody List<KaoQin> kaoQinList) {
        // 遍历 KaoQin 列表并发送通知
        for (KaoQin kaoQin : kaoQinList) {
            String openid = kaoQin.getOpenId();
            Integer studentId = kaoQin.getStudentId();

            // 根据 studentId 查询名字
            String studentName = studentsMapper.findNameById(studentId);
            String parentName = wxUserMapper.findParentNameById(studentId);

            Integer schedulesId = kaoQin.getSchedulesId();
            // 根据 schedulesId 查询课表名称
            Schedules schedules = schedulesMapper.findBySchedulesId(schedulesId);
            String scheduleName = schedules.getName();
            String classLocation = schedules.getLocation();
            String classTime = schedules.getStartTime().toString();

            Integer courseId = kaoQin.getCourseId();
            String courseName = coursesMapper.selectCourseNameByCourseId(courseId);
            Integer status = kaoQin.getStatus();

            if (status == 0) {
                // 准备通知内容
                Map<String, String> contentMap = new LinkedHashMap<>();
                contentMap.put("parentName", parentName);
                contentMap.put("courseName", courseName);
                contentMap.put("scheduleName", scheduleName);
                contentMap.put("studentName", studentName);
                contentMap.put("schoolTime", classTime);
                contentMap.put("classLocation", classLocation);

                // 发送通知
                String returnMsg = templateMsgService.sendCheckMsg(openid, contentMap);
                return R.suc("所有消息发送成功");
            }
        }
        return R.fail("所有消息发送失败");
    }


    /**
     * 设置公众号自定义菜单
     */
    @GetMapping("/menuCreate")
    public String menuCreate(){
        WxMenu wxMenu = new WxMenu();

        //创建一级菜单
        WxMenuButton firstBtn = new WxMenuButton();
        firstBtn.setName("学校简介");
        firstBtn.setType(WxConsts.MenuButtonType.VIEW);
        firstBtn.setUrl("https://www.baidu.com");


        WxMenuButton secondBtn = new WxMenuButton();
        secondBtn.setName("家校服务");

        WxMenuButton secondSubBtn_01 = new WxMenuButton();
        secondSubBtn_01.setName("师资力量");
        secondSubBtn_01.setType(WxConsts.MenuButtonType.VIEW);
        secondSubBtn_01.setUrl("https://www.baidu.com");


        WxMenuButton secondSubBtn_02 = new WxMenuButton();
        secondSubBtn_02.setName("课堂风采");
        secondSubBtn_02.setType(WxConsts.MenuButtonType.VIEW);
        secondSubBtn_02.setUrl("https://www.baidu.com");

        WxMenuButton secondSubBtn_03 = new WxMenuButton();
        secondSubBtn_03.setName("课程评价");
        secondSubBtn_03.setType(WxConsts.MenuButtonType.VIEW);
        secondSubBtn_03.setUrl("https://www.baidu.com");

        WxMenuButton secondSubBtn_04 = new WxMenuButton();
        secondSubBtn_04.setName("通知公告");
        secondSubBtn_04.setType(WxConsts.MenuButtonType.VIEW);
        secondSubBtn_04.setUrl("https://www.baidu.com");

        secondBtn.setSubButtons(Arrays.asList(secondSubBtn_01,secondSubBtn_02,secondSubBtn_03,secondSubBtn_04));



        WxMenuButton thirdBtn = new WxMenuButton();
        thirdBtn.setName("我的课程");

        WxMenuButton thirdSubBtn_01 = new WxMenuButton();
        thirdSubBtn_01.setName("账号绑定");
        thirdSubBtn_01.setType(WxConsts.MenuButtonType.VIEW);
        thirdSubBtn_01.setUrl(" http://uv3h3x.natappfree.cc/User");


        WxMenuButton thirdSubBtn_02 = new WxMenuButton();
        thirdSubBtn_02.setName("我的课表");
        thirdSubBtn_02.setType(WxConsts.MenuButtonType.VIEW);
        thirdSubBtn_02.setUrl("https://www.baidu.com");


        WxMenuButton thirdSubBtn_03 = new WxMenuButton();
        thirdSubBtn_03.setName("上课记录");
        thirdSubBtn_03.setType(WxConsts.MenuButtonType.VIEW);
        thirdSubBtn_03.setUrl("https://www.baidu.com");


        WxMenuButton thirdSubBtn_04 = new WxMenuButton();
        thirdSubBtn_04.setName("我要请假");
        thirdSubBtn_04.setType(WxConsts.MenuButtonType.VIEW);
        thirdSubBtn_04.setUrl("https://www.baidu.com");

        thirdBtn.setSubButtons(Arrays.asList(thirdSubBtn_01,thirdSubBtn_02,thirdSubBtn_03,thirdSubBtn_04));


        wxMenu.setButtons(Arrays.asList(firstBtn,secondBtn,thirdBtn));
        try {
            wxMpService.getMenuService().menuCreate(wxMenu);
            return "创建公众号菜单成功！";
        } catch (WxErrorException ex) {
            ex.printStackTrace();
            return "创建公众号菜单失败，失败原因！" + ex.getMessage();
        }

    }

    @RequestMapping(value = "/message", method = {RequestMethod.GET, RequestMethod.POST})
    @Operation(summary = "设置公众号自动回复功能")
    public String receiveMessage(@RequestBody(required = false) String xmlData,
                                 @RequestParam(value = "signature", required = false) String signature,
                                 @RequestParam(value = "timestamp", required = false) String timestamp,
                                 @RequestParam(value = "nonce", required = false) String nonce,
                                 @RequestParam(value = "echostr", required = false) String echostr) {
        if (xmlData == null || xmlData.isEmpty()) {
            // 处理微信的 GET 请求验证
            if (signature != null && timestamp != null && nonce != null && echostr != null) {
                boolean valid = wxMpService.checkSignature(timestamp, nonce, signature);
                if (valid) {
                    return echostr;
                }
                return "签名失败";
            }
            return "验证失败";
        }

        WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(xmlData);

        // 处理接收到的消息并生成回复
        WxMpXmlOutMessage outMessage = handleMessage(inMessage);

        return outMessage != null ? outMessage.toXml() : "";
    }

    private WxMpXmlOutMessage handleMessage(WxMpXmlMessage inMessage) {
        // 根据消息类型进行不同的处理
        switch (inMessage.getMsgType()) {
            case WxConsts.XmlMsgType.TEXT:
                return WxMpXmlOutMessage.TEXT()
                        .content(inMessage.getContent())
                        .fromUser(inMessage.getToUser())
                        .toUser(inMessage.getFromUser())
                        .build();

            case WxConsts.XmlMsgType.IMAGE:
                return WxMpXmlOutMessage.IMAGE()
                        .mediaId(inMessage.getMediaId())
                        .fromUser(inMessage.getToUser())
                        .toUser(inMessage.getFromUser())
                        .build();

            default:
                return WxMpXmlOutMessage.TEXT()
                        .content("暂时不支持该类型的消息")
                        .fromUser(inMessage.getToUser())
                        .toUser(inMessage.getFromUser())
                        .build();
        }
    }


    //根据openid查询用户信息
    @PostMapping("/getUserInfo")
    @Operation(summary = "根据openid查询用户信息")
    public R getUserInfo(@RequestParam("openid") String openid) {
        WxUser wxUser = wxUserService.findByOpenId(openid);
        if (wxUser == null) {
            return R.err("用户不存在");
        }
        return R.suc(wxUser);
        //输出对象

    }


    //根据父亲手机号等信息绑定孩子
    @PostMapping("/bindChild")
    @Operation(summary = "根据父亲手机号等信息绑定孩子")
    public R bindChild(@RequestBody BindChildDTO bindChildDTO) {

        String phone = bindChildDTO.getPhone();
        String studentName = bindChildDTO.getChildName();
        String code = bindChildDTO.getCode();
        String relation = bindChildDTO.getRelation();
        String openId = bindChildDTO.getOpenId();
        String name = bindChildDTO.getName();
        // 根据手机号和学生姓名在students表中查找
        Students student = studentsService.findByPhoneNumberAndName(phone, studentName);

        if (student != null ) {
            // 验证验证码
            String storedCode = redisTemplate.opsForValue().get(phone);
            if (code.equals(storedCode)) {
                // 验证成功，根据openid更新用户信息
                boolean b = wxUserService.updatePhoneAndRelationStudentId(openId, phone, student.getId(), relation,name);
                if (b) {
                    return R.suc("绑定成功");
                } else {
                    return R.err("绑定失败");
                }
            } else {
                return R.err("验证码验证失败");
            }
        }
        return R.err("未找到该孩子");
    }


        //点击发送短息
        //发送短信验证码
        @Operation(summary = "发送短信验证码")
        @GetMapping(value = "/send/{phone}")
        public Boolean code(@PathVariable String phone) {
            //1、从redis中获取验证码，如果获取到就直接返回
            String code = redisTemplate.opsForValue().get(phone);
            if(!StringUtils.isEmpty(code)) {
                return false;
            }

            //2、如果获取不到，就进行阿里云发送
            code = RandomUtil.getFourBitRandom();//生成验证码的随机值
            Map<String,Object> param = new HashMap<>();
            param.put("code", code);

            //调用方法
            boolean isSend = msmService.send(param,phone);
            if(isSend) {
                //往redis中设置数据：key、value、过期值、过期时间单位  MINUTES代表分钟
                redisTemplate.opsForValue().set(phone, code,5, TimeUnit.MINUTES);
                return true;
            } else {
                return false;
            }
        }


            //根据学生的id查询父母的openid



}
